﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Chromely.Core;
using Chromely.Core.Configuration;
using Chromely.Core.Host;
using Chromely.Core.Infrastructure;
using Chromely.Core.Logging;
using Chromely.Core.Network;
using static Chromely.Native.WinNativeMethods;

namespace Reader.Core
{
    public class ReaderConfiguration : IChromelyConfiguration
    {
        public bool UseFrameless { get; set; }
        /// <summary>Gets or sets the name of the application.</summary>
        public string AppName { get; set; }

        /// <summary>Gets or sets the start URL.</summary>
        public string StartUrl { get; set; }

        /// <summary>Gets or sets the application executable location.</summary>
        public string AppExeLocation { get; set; }

        /// <summary>Gets or sets the chromely version.</summary>
        public string ChromelyVersion { get; set; }

        /// <summary>Gets or sets the platform.</summary>
        public ChromelyPlatform Platform { get; set; }

        /// <summary>Gets or sets a value indicating whether debugging is enabled or not.</summary>
        public bool DebuggingMode { get; set; }

        /// <summary>Gets or sets the dev tools URL.</summary>
        public string DevToolsUrl { get; set; }

        /// <summary>Gets or sets the command line arguments.</summary>
        public IDictionary<string, string> CommandLineArgs { get; set; }

        /// <summary>Gets or sets the command line options.</summary>
        public List<string> CommandLineOptions { get; set; }

        /// <summary>Gets or sets the controller assemblies.</summary>
        public List<ControllerAssemblyInfo> ControllerAssemblies { get; set; }

        /// <summary>Gets or sets the custom settings.</summary>
        public IDictionary<string, string> CustomSettings { get; set; }

        /// <summary>Gets or sets the event handlers.</summary>
        public List<ChromelyEventHandler<object>> EventHandlers { get; set; }

        /// <summary>Gets or sets the extension data.</summary>
        public IDictionary<string, object> ExtensionData { get; set; }

        /// <summary>Gets or sets the java script executor.</summary>
        public IChromelyJavaScriptExecutor JavaScriptExecutor { get; set; }

        /// <summary>Gets or sets the URL schemes.</summary>
        public List<UrlScheme> UrlSchemes { get; set; }

        /// <summary>Gets or sets the cef download options.</summary>
        public CefDownloadOptions CefDownloadOptions { get; set; }

        /// <summary>Gets or sets the window options.</summary>
        public IWindowOptions WindowOptions { get; set; }

        public ReaderConfiguration()
        {
            AppName = "阅读器";
            Platform = ChromelyRuntime.Platform;
            AppExeLocation = AppDomain.CurrentDomain.BaseDirectory;
            StartUrl = $"http://localhost/";
            //StartUrl = "res://wwwroot/index.html";
#if DEBUG
            DebuggingMode = true;
#else
            DebuggingMode = false;
#endif
            UrlSchemes = new List<UrlScheme>();
            CefDownloadOptions = new CefDownloadOptions();
            CommandLineArgs = new Dictionary<string, string>
            {
                ["disable-web-security"] = "1"
            };

            UseFrameless = true;
            //var styles = WindowStyles.WS_POPUPWINDOW | WindowStyles.WS_CLIPCHILDREN | WindowStyles.WS_CLIPSIBLINGS
            //    | WindowStyles.WS_SIZEBOX | WindowStyles.WS_MINIMIZEBOX | WindowStyles.WS_MAXIMIZEBOX;
            //var styles = WindowStyles.WS_OVERLAPPEDWINDOW;
            //var exStyles = WindowExStyles.WS_EX_APPWINDOW | WindowExStyles.WS_EX_WINDOWEDGE;
            WindowOptions = new WindowOptions
            {
                Title = AppName,
                RelativePathToIconFile = "Reader.ico",
                DisableMinMaximizeControls = true,
                //CustomStyle = new WindowCustomStyle((long)styles, (long)exStyles),
                //UseCustomStyle = true,
                //KioskMode = true,
                //WindowState = WindowState.Maximize,
                //WindowFrameless = true,
                FramelessOption = new FramelessOption
                {
                    UseDefaultFramelessController = true,
                    UseWebkitAppRegions = true,
                    IsDraggable = (nativeHost, point) =>
                    {
                        const int draggableHeight = 50;
                        const int nonDraggableRightOffsetWidth = 150;

                        var size = nativeHost.GetWindowClientSize();
                        var right = size.Width - point.X;
                        return point.Y <= draggableHeight && right > nonDraggableRightOffsetWidth;
                    }
                },
                StartCentered = true
            };

            UrlSchemes.AddRange(new List<UrlScheme>()
            {
                new UrlScheme("local-resource","res",string.Empty,string.Empty,UrlSchemeType.Resource,false),
                //new UrlScheme("app-resource","app","reader.com", string.Empty, UrlSchemeType.Custom, false),
                //new UrlScheme("custom-http","http","localhost",string.Empty,UrlSchemeType.Custom,false),
                //new UrlScheme("custom-https", "https", string.Empty, string.Empty, UrlSchemeType.Custom, false),
                //new UrlScheme("command", "cmd", "reader.com", string.Empty, UrlSchemeType.Command, false),
                //new UrlScheme("ajax", "ajax", string.Empty, string.Empty, UrlSchemeType.External, false)
            });

            ControllerAssemblies = new List<ControllerAssemblyInfo>();

            var appDirectory = AppDomain.CurrentDomain.BaseDirectory;
            var externalControllerFile = Path.Combine(appDirectory, "Chromely.External.Controllers.dll");
            if (File.Exists(externalControllerFile))
            {
                ControllerAssemblies.RegisterServiceAssembly("Chromely.External.Controllers.dll");
                var assemblyOptions = new AssemblyOptions(externalControllerFile, null, "app");
                UrlSchemes.Add(new UrlScheme("assembly-resource", "assembly", "reader", string.Empty, UrlSchemeType.AssemblyResource, false, assemblyOptions));

                var mixAssemblyOptions = new AssemblyOptions(externalControllerFile, null, "appresources");
                UrlSchemes.Add(new UrlScheme("mix-assembly-resource", "mixassembly", "reader", string.Empty, UrlSchemeType.AssemblyResource, false, mixAssemblyOptions));
            }
#if DEBUG
            CustomSettings = new Dictionary<string, string>()
            {
                ["cefLogFile"] = "logs\\chromely.cef.log",
                ["logSeverity"] = "info",
                ["locale"] = "zh-CN",
                ["userdata"] = "userdata",
                ["cachepath"] = "cache",
                ["LogSeverity"] = "default" //"disable"
                //["ResourcesDirPath"]="resource"
            };
#else
            CustomSettings = new Dictionary<string, string>()
            {
                ["locale"] = "zh-CN",
                ["cachepath"] = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "temp", "reader.cache"),
                ["LogSeverity"] = "disable"
            };
#endif
        }

        public static IChromelyConfiguration CreateForRuntimePlatform()
        {
            return CreateForPlatform(ChromelyRuntime.Platform);
        }

        public static IChromelyConfiguration CreateForPlatform(ChromelyPlatform platform)
        {
            IChromelyConfiguration config;

            try
            {
                config = new ReaderConfiguration();

                switch (platform)
                {
                    case ChromelyPlatform.Windows:
                        config.WindowOptions.CustomStyle = new WindowCustomStyle(0, 0);
                        config.WindowOptions.UseCustomStyle = false;
                        break;

                    case ChromelyPlatform.Linux:
                        config.CommandLineArgs = new Dictionary<string, string>
                        {
                            ["disable-gpu"] = "1"
                        };

                        config.CommandLineOptions = new List<string>()
                        {
                            "no-zygote",
                            "disable-gpu"
                        };
                        break;

                    case ChromelyPlatform.MacOSX:
                        break;
                }

                return config;
            }
            catch (Exception exception)
            {
                config = null;
                Logger.Instance.Log.Error(exception);
            }

            return config;
        }
    }
}
